lv1= lv2= type=
log ana
log ana todo
http://a.add.my/log_storage
〖E:\uninote\additional_item\log_storage\bin\Analysis〗
obsolete:
http://a.myres.my/log.viewer/
〖E:\uninote\mynote_res\logviewer〗
〖E:\uninote\mynote_res\log_analysis〗
exception分析工具,相同的堆栈,md5作为标示
nginx log分析 耗时记录
定时器分析:??
E:\uninote\mynote\art_workman\start.php
E:\uninote\mynote\art_workman\Application\Mlog.php
分为两部分,解析存储 + 读取
排错
mynote_indexfile 清理,重新分析
注意 note
注意:编码、linefeed
目前只有mynote_log的分析有多行的问题,其他的日志都是单行记录。
message 过长 - 删除日志 临时解决 -- try/catch
lv1= lv2= type=
log reader config
已经内联分析,查询时即执行 ana。
---------- local:
<?php
$g_config["pwd"] = "root";
/*日志解析路径*/
$g_config['item'] = [
[
"api" => "mynote_log", //模块名称
"path" => "E:/uninote/mynote/basic/runtime/seaslog/default" //实际情况日志路径
],
[
"api" => "mynote_login",
"path" => "E:/uninote/mynote/basic/runtime/seaslog/login"
],
[
"api" => "mynote_request",
"path" => "E:/uninote/mynote/basic/runtime/logs/logs.txt"
]
];
---------- online:
<?php
$g_config["pwd"] = "root123.";
/*日志解析路径*/
$g_config['item'] = [
[
"api" => "mynote_log", //模块名称
"path" => "/home/www/mynote/basic/runtime/seaslog/default" //实际情况日志路径
],
[
"api" => "mynote_login",
"path" => "/home/www/mynote/basic/runtime/seaslog/login"
],
[
"api" => "mynote_request",
"path" => "/home/www/mynote/basic/runtime/logs/logs.txt"
]
];
lv1= lv2= type=
log ana design
记录、分析、查看
user mynote_login mynote_request mynote_log
筛选(filter):按人、时间
request.id 显示在头部(红色),log.id 显示在每条日志中(绿色区域)
日志内容显示在蓝色区域
post参数显示在黄色区域,可以直接复制到api/tests,进行调试
过滤条件(每张表可能都有过滤字段):
uid, 手机号、reqnum、时间段
message like
uri
请求消耗时间 > 200ms
要点:
查询的主要脉络应该是request表,但request可能不和任何user、login(无登录记录)、log(此request无任何日志输出)表关联
查询结果排序:
按request id排序,则无法按照日志发生的先后顺序显示;
按log id排序,因为有的request无log,因此此类request显示有问题。
解决方案:
lv1= lv2= type=todo
cyb:使用日志时间排序
IFNULL(log.datetime,r.datetime) AS 记录时间,
lv1= lv2= type=
config
同 reader config
log reader config
lv1= lv2= type=
log ana 日志
E:\uninote\additional_item\log_storage\bin\Analysis\Analysis.php
E:\uninote\additional_item\log_storage\logs\log.txt
check list
SHA-1: 4312417640264ac9086b466fccd2571eb85c5ca9
* bug fix:添加common.php 的引用
lv1= lv2= type=
log ana 部署
log reader config
nginx config: E:\back\git\mynote\online\nginx\vhost\additional_item_82.conf
sql/*.sql 初始化
部署步骤
- 在php.ini中配置seaslog的输出模板:
seaslog.default_template = "%t -||- %L -||- %R -||- %C -||- %F -||- %Q -||- %M"
- 在mynote数据库中执行所有子目录下的create.sql,生成对应的日志表。

- 执行一次登录,并随意浏览网站
- 运行http://a.add.my/log_storage/ana.php,手动将生成的日志解析并存储到数据库中
或者直接访问 http://a.add.my/log_storage/,会自动分析
commits
tbname & logpath 可以从url中覆盖
ed83711eca2a13c16db4d3a38a26983a397c7747
eg:
http://a.add.my/log_analysis/mynote_request/process.php?logpath=logs.txt&tbname=abc
注意,必要时参数需要urlEncode
SHA-1: d04f40f687b150a79162145a5b6b196eaa31c5e3
* 【更新】- 日志采集功能更新,更改文件记录末尾行数存储mysql避免行号不对的错误
lv1= lv2= type=
ana.php 一次性分析处理所有日志
直接 http 访问:
http://a.add.my/log_storage/ana.php
结果见日志
config
也可以在访问 GUI 时触发
lv1= lv2= type=
ana 优化 fgets
这个有性能问题:
$lines = explode("\n", $content);
$countLines = count($lines);
lv1= lv2= type=
mynote seaslog 日志解析
文件夹:mynote_log
数据库表结构:
datetime level uri class filename reqid message
其中,需要将level字段翻译为level数字,参见SeasLog 共将日志分成8个级别
seaslog配置:
seaslog.default_template = "%t %L %R %C %F %Q %M"
seaslog.default_logger=default
seaslog.disting_folder = 1
seaslog.disting_type=0
seaslog.disting_by_hour=0
seaslog.use_buffer=1
seaslog.buffer_size=100
seaslog.level=8
seaslog.trace_error=1
seaslog.trace_exception=0
优化:
放到开头,作为一条log的标记。
fgets,不要一次性读取所有文件。
%R 不用了
lv1=mynote lv2= type=done
不要存成一行,显示时需要换行
[cmd]: git commit -m 'update' 2>&1[update_0137822208 63a2a1e] 'update' 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 1535965471
white-space: pre-line;
lv1=mynote lv2= type=done
将上次的读取位置保存到mysql数据库中:
log_analysis/common.php
$indexfile_path = "./last_end_index.txt";
if (!file_exists($indexfile_path)) {
file_put_contents($indexfile_path, 0);
}
lv1=mynote lv2= type=done
mynote_log 加入logger字段
用于保存logger
lv1=mynote lv2= type=done
logger时间精确到毫秒
时间使用%t,修改解析处:
"%t -||- %L -||- %C -||- %F -||- %Q -||- %M"
实时分析 位置缓存
为了支持实时分析,在mynote_indexfile表中记录上次分析到的位置(文件偏移量)
注意大小写问题
lv1= lv2= type=
mynote_login uid + sessionid 重复问题
lv1=mynote lv2= type=done
reqnum用get_time?重复太多
log sessionid重复查询:
select count(*) as cnt, login.sessionid
from mynote_login login
GROUP BY login.sessionid
HAVING cnt >1
特定id查看:
SELECT * FROM `mynote_login` WHERE sessionid = 'k18v46c4k11m7tjs5vhndc0ktv'
mynote_request 记录请求时间
reqnum 重复查询:
SELECT count(*) as cnt, r.reqnum, r.sessionid
from mynote_request r
GROUP BY r.reqnum
having cnt > 1
select *from mynote_request where reqnum = 6951333
关联sessionid和用户
在用户登录时记录到logger login:E:\uninote\mynote\basic\runtime\seaslog\login
但用户退出登录后,下次再登录,sessionid并不会改变。此时一条log就会对应两个登录记录(用户),查询时就是一条log显示两次。
解决办法:注销后前端清除sessionid
* 注销后删除cookie,方便日志分析
但这种方法并不一定有效,比如:服务器上session过期,此时重新登录,还是会存在同一个sessionid两次登录的情况
终极办法:* opt: 避免登录时复用 cookie,保证每个 session 使用的 cookie 都是唯一的
但这样会丢掉登录前的操作日志
用uid+sid做判定,如果仍然是上次用户,忽略此次 login 记录;否则重新分配 sid
或者合并可能的多用户
临时表去重,可能存在性能问题
* feat: mynote_login 通过临时表去重
- LEFT JOIN mynote_login AS login ON
+ LEFT JOIN (SELECT uid, sessionid from mynote_login GROUP BY uid, sessionid) AS login ON
测试点
图片接口
dev tools
TRUNCATE table mynote_log;
truncate table mynote_request;
update mynote_indexfile set last_end_index = 0 where indexfile_path = 'E:/uninote/mynote/basic/runtime/seaslog/default/20190930.log';
select * from mynote_indexfile where indexfile_path = 'E:/mynote/basic/runtime/seaslog/default/20190422.log';
SELECT * from mynote_log;
test cases
empty
one line
one line + oneline
mline + mline
oneline + mline
mline + online
lv1= lv2= type=
mynote request log
SHA-1: f69244347bd8a3cbad51a5cd5a988ccec973c11d
* 用 finally 保证每个请求的 log 完整(REQUEST_END 的记录)
php error reporting/handling exception 异常、错误处理
finally {
/* CT log end */
CT_log("--REQUEST_END:" . $g_REQUEST_URI . "|| PHPSESSID: " . $g_PHPSESSID . "|| rnum: " . $request_num .
"|| time: " . (get_time() - $g_begintime) . "s");
CT_flush(true);
}
lv1= lv2= type=
mynote log 混合编码
windows 下 yii redis 抛出的错是 gbk 编码的,其他都是utf8:
[error][yii\redis\Connection] Failed to open redis DB connection (localhost:6379, database=0): 10061 - 由于目标计算机积极拒绝,无法连接。
lv1= lv2= type=
支持 date/delta 参数,date 优先,-- 隔天丢失问题
分析前一天的:
http://uninote.com.cn:82/log_storage/ana.php?delta=1
分析指定日期:
http://uninote.com.cn:82/log_storage/ana.php?date=20210706
lv1= lv2= type=
nginx 访问日志处理
已经暂定copy,没法使用 ln -s
docker cp /usr/local/nginx/logs/ut-online.access.log mynote-online:/home/www/mynote/basic/runtime/logs/nginx.log
# vi /etc/crontab
* * * * * root docker cp /usr/local/nginx/logs/ut-online.access.log mynote-online:/home/www/mynote/basic/runtime/logs/nginx.log >> /tmp/docker-cp.log 2>&1
然后访问:http://uninote.com.cn:82/log_storage/ana.php
查看日志:
tail -f /home/www/additional_item/log_storage/logs/log.txt
[
"api" => "xjc_nignx",
"path" => "/home/www/mynote/basic/runtime/logs/nginx.log"
],
[
"api" => "xjc_nignx",
"path" => "/home/www/mynote/basic/runtime/logs/nginx-old.log"
]
seo sql
SELECT u.nick , n.* from xjc_nginx n
LEFT JOIN mynote_login l on n.sessid = l.sessionid
LEFT JOIN `user` u on l.uid = u.id
where time > '2020-07-06'
-- and ua like '%google%'
and referer like '%www.google%'
and request like '%/book/%'
-- and request like '%/book/%'
SELECT* from xjc_nginx where time > '2021-07-06 22'
SELECT* from xjc_nginx where
time > '2021-07-06 22'
and ua like '%mobile%'
select * from xjc_nginx WHERE sessid = '4icdu9f6mns97pvueftfqpmtd0'
and request like '%login%'
SELECT* from xjc_nginx where ip = '180.169.253.136'
and request like '%/book/%'
SELECT* from xjc_nginx where time > '2020-07-06'
-- and ua like '%google%'
and referer like '%www.baidu.com%'
SELECT uid, sessionid from mynote_login
GROUP BY uid, sessionid
desc mynote_login
SELECT DISTINCT uid, sessionid from mynote_login
where uid = 1039 and sessionid='001bkbvhrbjghl0h0hl4kut0u7'
开源 IP 地址定位库 ip2region 1.9.0 发布
https://cloud.tencent.com/developer/article/1578818?from=information.detail.php%E6%9C%80%E6%96%B0ip%E5%9C%B0%E5%9D%80%E5%BA%93
IPIP.net - 实际使用
unicyber
2848
7857
https://www.ipip.net/product/client.html
https://github.com/ipipdotnet/ipdb-php
feat: ip 反解城市